#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
@Author: kindey
@Date: 2025/8/12
@Description: 
"""
import logging
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
from django.conf import settings
from apps.services.dev_data_service import DevDataService as DevDS
from apps.utils.string_utils import generate_random_string as grs

class PlotService:
    logger = logging.getLogger(__name__)
    @staticmethod
    def plot_one_dev(dev_id, start_time, end_time, is_save_file):
        """
        绘制单个设备折线图

        :param dev_id:设备id
        :param start_time:开始时间
        :param end_time:结束时间
        :param is_save_file:是否保存图片
        :return: file_path:图片路径
        """
        data_type = "rec"
        d = DevDS()
        dev_data_list = d.get_dev_data_by_condition(data_type, dev_id, start_time, end_time)
        columns = ['data_time', 'data_value']
        data = pd.DataFrame(dev_data_list, columns=columns)
        data_value_str = f'data_value_{dev_id}'
        data.rename(columns={'data_value': data_value_str}, inplace=True)
        data['data_time'] = pd.to_datetime(data['data_time'])

        # 设置中文字体和解决负号显示问题
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        # 绘制折线图
        plt.figure(figsize=(10, 6))
        sns.lineplot(data=data, x='data_time', y=data_value_str)

        # 假设 n 为指定的间隔步长，可根据需要调整
        n = ((len(data) // 72) + 1) * 3
        xticks_values = data['data_time'][::n]
        # 格式化显示格式
        xticks_labels = xticks_values.dt.strftime('%Y-%m-%d %H:%M')
        # 控制 x 轴标签密度
        plt.xticks(ticks=xticks_values, labels=xticks_labels, rotation=45)

        plt.xlabel('时间')
        plt.ylabel('数据值')
        plt.title(f'设备{dev_id}数据趋势图--开始时间：{start_time}--结束时间：{end_time}')
        plt.legend()
        plt.grid(True)
        plt.tight_layout()

        file_path = ""
        if is_save_file:
            static_root = settings.STATIC_ROOT
            time_str = f"{start_time.replace(':', '')}__{end_time.replace(':', '')}"
            file_name = f"plot_one_dev_{dev_id}__{time_str}__{grs()}.png"
            file_path = f"{static_root}\\{file_name}"
            plt.savefig(file_path)

        plt.show()
        plt.close()
        return file_path

    @staticmethod
    def plot_two_dev(dev_id_1, dev_id_2, start_time, end_time, is_save_file):
        """
        绘制两个设备对比折线图

        :param dev_id_1:设备1id
        :param dev_id_2:设备2id
        :param start_time:开始时间
        :param end_time:结束时间
        :param is_save_file:是否保存图片
        :return: file_path:图片路径
        """
        data_type = "rec"
        d = DevDS()
        dev_data_list1 = d.get_dev_data_by_condition(data_type, dev_id_1, start_time, end_time)
        dev_data_list2 = d.get_dev_data_by_condition(data_type, dev_id_2, start_time, end_time)
        columns = ['data_time', 'data_value']
        # 将 dev_data_list1 和 dev_data_list2 转换成 DataFrame
        df1 = pd.DataFrame(dev_data_list1, columns=columns)
        df2 = pd.DataFrame(dev_data_list2, columns=columns)
        # 重命名 data_value 列
        data_value_str1=f'data_value_{dev_id_1}'
        data_value_str2=f'data_value_{dev_id_2}'
        df1.rename(columns={'data_value': data_value_str1}, inplace=True)
        df2.rename(columns={'data_value': data_value_str2}, inplace=True)
        # 使用 data_time 作为关联字段合并两个 DataFrame
        data = pd.merge(df1, df2, on='data_time', how='outer')
        data['data_time'] = pd.to_datetime(data['data_time'])

        # 设置中文字体和解决负号显示问题
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        # 创建图形和双Y轴
        fig, ax1 = plt.subplots(figsize=(10, 6))

        # 绘制第一个设备的数据（左Y轴）
        sns.lineplot(data=data, x='data_time', y=data_value_str1, ax=ax1, label=data_value_str1)
        ax1.set_xlabel('时间')
        ax1.set_ylabel(data_value_str1)
        ax1.grid(True)

        # 创建第二个Y轴
        ax2 = ax1.twinx()

        # 绘制第二个设备的数据（右Y轴）
        sns.lineplot(data=data, x='data_time', y=data_value_str2, ax=ax2, color='orange', label=data_value_str2)
        ax2.set_ylabel(data_value_str2)
        # 设置标题
        plt.title(f'设备{dev_id_1}与设备{dev_id_2}数据对比趋势图--开始时间：{start_time}--结束时间：{end_time}')

        # 控制 x 轴标签密度
        n = ((len(data) // 72) + 1) * 3
        xticks_values = data['data_time'][::n]
        xticks_labels = xticks_values.dt.strftime('%Y-%m-%d %H:%M')
        ax1.set_xticks(xticks_values)
        ax1.set_xticklabels(xticks_labels, rotation=45)

        # 合并两个轴的图例，解决标签重叠问题
        lines1, labels1 = ax1.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')

        # 清除ax2的图例避免重叠
        ax2.get_legend().remove()

        # 调整布局
        plt.tight_layout()

        file_path = ""
        if is_save_file:
            static_root = settings.STATIC_ROOT
            time_str = f"{start_time.replace(':', '')}__{end_time.replace(':', '')}"
            file_name = f"plot_two_dev_{dev_id_1}_{dev_id_2}__{time_str}__{grs()}.png"
            file_path = f"{static_root}\\{file_name}"
            plt.savefig(file_path)

        plt.show()
        plt.close()
        return file_path

    @staticmethod
    def plot_more_dev(dev_ids : list[int], start_time, end_time, is_save_file):
        """
        绘制两个设备对比折线图

        :param dev_ids:设备id数组
        :param start_time:开始时间
        :param end_time:结束时间
        :param is_save_file:是否保存图片
        :return: file_path:图片路径
        """
        data_type = "rec"
        d = DevDS()
        columns = ['data_time', 'data_value']
        data = None
        # 先收集所有需要的列名
        data_value_columns = []
        # 假设 n 为指定的间隔步长，可根据需要调整
        n = 1
        for i, dev_id in enumerate(dev_ids):
            dev_data_list = d.get_dev_data_by_condition(data_type, dev_id, start_time, end_time)
            df = pd.DataFrame(dev_data_list, columns=columns)
            data_value_str = f'data_value_{dev_id}'
            df.rename(columns={'data_value': data_value_str}, inplace=True)
            data_value_columns.append(data_value_str)
            if i == 0:
                data = df
                n = ((len(data) // 72) + 1) * 3
            else:
                data = pd.merge(data, df, on='data_time', how='outer')

        data['data_time'] = pd.to_datetime(data['data_time'])

        # 将数据转换为适合 Seaborn 的长格式
        data_melted = (data[['data_time'] + data_value_columns]
                       .melt(id_vars='data_time', value_vars=data_value_columns, var_name='variable',
                             value_name='value'))

        # 归一化处理：按每个变量做 Min-Max Scaling
        def min_max_normalize(group):
            min_val = group['value'].min()
            max_val = group['value'].max()
            # 避免除零情况
            if max_val - min_val != 0:
                group['value_normalized'] = (group['value'] - min_val) / (max_val - min_val)
            else:
                group['value_normalized'] = 0
            return group

        data_normalized = data_melted.groupby('variable', group_keys=False).apply(min_max_normalize)

        dev_id_str = ''
        if len(dev_ids) == 1:
            dev_id_str += f'{dev_ids[0]}'
        elif len(dev_ids) == 2:
            dev_id_str = f'{dev_ids[0]},{dev_ids[1]}'
        elif len(dev_ids) == 3:
            dev_id_str = f'{dev_ids[0]},{dev_ids[1]},{dev_ids[2]}'
        else:
            dev_id_str = f'{dev_ids[0]},{dev_ids[1]}...{dev_ids[len(dev_ids) - 1]}'
        time_str = f'{start_time.replace(":", "")}__{end_time.replace(":", "")}'

        # 设置中文字体和解决负号显示问题
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False

        plt.figure(figsize=(12, 6))
        sns.lineplot(data=data_normalized, x='data_time', y='value_normalized', hue='variable')

        xticks_values = data_normalized['data_time'][::n]
        xticks_labels = xticks_values.dt.strftime('%Y-%m-%d %H:%M')  # 格式化显示格式
        # 控制 x 轴标签密度
        plt.xticks(ticks=xticks_values, labels=xticks_labels, rotation=45)

        plt.xlabel('时间/样本点')
        plt.ylabel(rf'值')
        plt.title(f'设备{dev_id_str}数据对比趋势图--时间：{time_str}')
        plt.legend()
        plt.grid(True)
        plt.tight_layout()  # 自动调整布局
        file_path = ""
        if is_save_file:
            static_root = settings.STATIC_ROOT
            file_name = f"plot_more_dev_{dev_id_str}__{time_str}__{grs()}.png"
            file_path = f"{static_root}\\{file_name}"
            plt.savefig(file_path)

        plt.show()
        plt.close()
        return file_path

class BarService:
    logger = logging.getLogger(__name__)
    def bar_one_dev(self, dev_id, start_time, end_time):
        """
        汇总单个设备主状图
        """

class PieService:
    logger = logging.getLogger(__name__)
    def pie_one_dev(self, dev_id, start_time, end_time):
        """
        汇总单个设备饼状图
        """